void BuildAIBullet(Tank* tank)                   //AI坦克的子弹发射（含有对my_tank的文件读取，只读取my_tank坐标）
{
	if (tank->CD == 15)//我们需要发射子弹
	{
		if (!(rand() % 11))//有十分之一的几率
		{
			BuildBullet(*tank);
			tank->CD = 0;
		}
	}
	else
		tank->CD++;//初始化中被设置为0
		//上面这一部分是自由开火时间，但是有一部分还是可能超出后还没开一次火。你以为自己气运逆天

	if (tank->CD >= 14)//一枪不发是不可能的，我来一个强制发射
	{
		if (tank->y == 38)//老家底部，反正就是直捣黄龙
		{
			if (tank->x < 20)//老家左边（坐标画出来兄弟）
			{
				if (tank->direction == RIGHT)//枪口刚刚好对准老家
				{
					BuildBullet(*tank);//对准老家，开火
					tank->CD = 0;
				}
			}
			else
			{
				if (tank->direction == LEFT)//枪口刚刚好对准老家
				{
					BuildBullet(*tank);//对准老家，开火
					tank->CD = 0;
				}
			}
		}
		else if (tank->x == my_tank.x + 1 || tank->x == my_tank.x || tank->x == my_tank.x - 1)
		{//AI坦克炮口对到MY坦克的身上，结局妙不可言
			if ((tank->direction == DOWN && my_tank.y > tank->y) || (tank->direction == UP && my_tank.y < tank->y))
			{                  //如果AI坦克炮口朝下而且刚刚好MY坦克就在坦克炮口之下
							   //or AI坦克炮口朝上而且刚刚好MY坦克就在坦克炮口之上
				int big = my_tank.y, smal = tank->y, i;
				if (my_tank.y < tank->y)//如果MY坦克处于AI坦克上面
				{
					big = tank->y;//大
					smal = my_tank.y;//小
				}//调换一下
				for (i = smal + 2; i < big - 2; i++)//判断AI炮口的直线上两坦克间有无障碍
				{
					if (map[i][tank->x] != 0 || map[i][tank->x] != 5)//如果有障碍
						break;
				}
				if (i == big - 1)//若i走到big-1说明无障碍
				{
					BuildBullet(*tank);     //则发射子弹
					tank->CD = 0;
				}
			}
		}
		else if (tank->y == my_tank.y + 1 || tank->y == my_tank.y || tank->y == my_tank.y - 1) //AI坦克在横向上"炮口"对准我的坦克
		{
			if ((tank->direction == RIGHT && my_tank.x > tank->x) || (tank->direction == LEFT && my_tank.x < tank->x))
			{                  //若是AI朝右并且我的坦克在AI坦克右方(数值大的在下面)或者AI朝左我的坦克在AI左方
				int big = my_tank.y, smal = tank->y, i;
				if (my_tank.x < tank->x)
				{
					big = tank->x;
					smal = my_tank.x;
				}
				for (i = smal + 2; i <= big - 2; i++)  //判断AI炮口的直线上两坦克间有无障碍
					if (map[tank->y][i] != 0 || map[tank->y][i] != 5)      //若有障碍
						break;
				if (i == big - 1)   //若i走到big-1说明无障碍
				{
					BuildBullet(*tank);     //则发射子弹
					tank->CD = 0;
				}
			}
		}
	}
	/*
	首先确定了AI坦克的自由反射子弹的能力和到了一定时间后会发射子弹的几率。
	之后再确定了AI坦克跑到老家底部后面对老家一定开火的底气。
	最后如果在路上碰到MY坦克，中间没有障碍物的话，AI也不会客气的代码
	*/
}
void BuildBullet(Tank tank)                       //子弹发射（人机共用）玩家坦克直接调用该函数，AI通过AIshoot调用
{                   //∵实现方式为顺序循环建立子弹，每次调用改变的bullet数组元素都不同
				   //∴为了方便,不将bullet放入参数,bullet作为全局变量使用
	switch (tank.direction)//确定下子弹方向
	{
	case UP:
		bullet[bul_num].x = tank.x;
		bullet[bul_num].y = tank.y - 2;
		bullet[bul_num].direction = 1;
		break;
	case DOWN:
		bullet[bul_num].x = tank.x;
		bullet[bul_num].y = tank.y + 2;
		bullet[bul_num].direction = 2;
		break;
	case LEFT:
		bullet[bul_num].x = tank.x - 2;
		bullet[bul_num].y = tank.y;
		bullet[bul_num].direction = 3;
		break;
	case RIGHT:
		bullet[bul_num].x = tank.x + 2;
		bullet[bul_num].y = tank.y;
		bullet[bul_num].direction = 4;
		break;
	}//这里的图像建立可都是2的
	bullet[bul_num].exist = 1;    //子弹被建立,此值为1则此子弹存在
	bullet[bul_num].initial = 1;  //子弹处于初建立状态
	bullet[bul_num].my = tank.my;   //如果是我的坦克发射的子弹bullet.my=1，否则为0
	bul_num++;
	if (bul_num == BULLET_NUM)        //如果子弹编号增长到20号，那么重头开始编号
		bul_num = 0;                 //考虑到地图上不可能同时存在20颗子弹，所以数组元素设置20个
}
void BulletFly(Bullet bullet[BULLET_NUM])//子弹移动与打击（人机共用）
{
	int i, j;
	for (i = 0; i < BULLET_NUM; i++)//存在地图上的子弹数量
	{
		if (bullet[i].exist)//如果子弹存在的话
		{
			if (bullet[i].initial == 0)//如果子弹不是初建立
			{
				if (map[bullet[i].y][bullet[i].x] == 0 || map[bullet[i].y][bullet[i].x] == 5)//子弹移动未遇到障碍物
					ClearBullet(bullet[i].x, bullet[i].y, BulletCheak(bullet[i].x, bullet[i].y));//抹除子弹图像
				switch (bullet[i].direction)
				{
				case UP:(bullet[i].y)--; break;
				case DOWN:(bullet[i].y)++; break;
				case LEFT:(bullet[i].x)--; break;
				case RIGHT:(bullet[i].x)++; break;
				}
			}
			int collide = BulletCheak(bullet[i].x, bullet[i].y);////判断子弹当前位置情况,判断子弹是否碰撞,是否位于水面上
			if (collide)                                      //如果检测到当前子弹坐标无障碍(无碰撞)（包括在地面上与在水面上）
				PrintBullet(bullet[i].x, bullet[i].y, collide);       //则打印子弹，若有碰撞则不打印
			else
				BulletHit(&bullet[i]);     //若有碰撞则执行子弹碰撞函数

			if (bullet[i].initial)             //若子弹初建立，则把初建立标记去除
				bullet[i].initial = 0;
			for (j = 0; j < BULLET_NUM; j++)  //子弹间的碰撞判断,若是我方子弹和敌方子弹碰撞则都删除
																   //若为两敌方子弹则无视
				if (bullet[j].exist && j != i && (bullet[i].my || bullet[j].my) && bullet[i].x == bullet[j].x && bullet[i].y == bullet[j].y)
				{                              //同样的两颗我方子弹不可能产生碰撞
					bullet[j].exist = 0;
					bullet[i].exist = 0;
					ClearBullet(bullet[j].x, bullet[j].y, BulletCheak(bullet[j].x, bullet[j].y));  //抹除j子弹图形,子弹i图形已被抹除
					break;
				}
		}
	}
}
void BulletHit(Bullet* bullet)                     //子弹碰撞（人机共用）含tank全局变量修改，只通过BulletFly调用，
{                                                              //子弹间的碰撞不在本函数，由Bulletshoot（）进行检查处理
										 //∵每次打中的坦克都不一样，不可能把所有坦克放在参数表中
	int x = bullet->x;            //∴这里的Tank使用全局变量
	int y = bullet->y;            //这里传入的值是子弹坐标,这两个值不需要改变

	int i;

	if (map[y][x] == 1 || map[y][x] == 2)//子弹碰到砖块
	{
		if (bullet->direction == UP || bullet->direction == DOWN)//如果子弹是纵向（上下）
			for (i = -1; i <= 1; i++)
				if (map[y][x + i] == 1 || map[y][x + i] == 2)
				{   //如果子弹打中砖块两旁为砖块,则删除砖,若不是(一旁为坦克或其他地形)则忽略
					map[y][x + i] = 0;//碎砖（改成背景）
					GoToxy(2 * x + 2 * i, y);
					SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED); //背景黑色
					printf("  ");
				}
		if (bullet->direction == LEFT || bullet->direction == RIGHT)     //若子弹是横向的  (与子弹纵向实现同理)
			for (i = -1; i <= 1; i++)
				if (map[y + i][x] == 1 || map[y + i][x] == 2)
				{
					map[y + i][x] = 0;
					GoToxy(2 * x, y + i);
					SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED); //背景黑色
					printf("  ");
				}
		bullet->exist = 0;//这颗子弹已经不存在了
	}

	else if (map[y][x] == 4 || map[y][x] == 6)  //子弹碰到边框或者不可摧毁方块
		bullet->exist = 0;//子弹还是得消失

	else if (bullet->my && map[y][x] >= 100 && map[y][x] < 104)//如果是我的子弹碰到AI坦克
	{
		int num = map[y][x] % 100;   //map[y][x]%100 等同于 tank.num ，可通过map值读取该坦克信息
		if (AI_tank[num].model == 3 && AI_tank[num].color == 2)   //若为firm tank,且color==2。
																							//该坦克为绿色,表明没有受到伤害
			AI_tank[num].color = 3;                        //则变成黄色，color=3为黄色
		else if (AI_tank[num].model == 3 && AI_tank[num].color == 3)
			AI_tank[num].color = 4;                        //4为红色
		else                       //其他类型的坦克或者firm tank为红色的情况
		{
			AI_tank[num].alive = 0;
			ClearTank(AI_tank[num].x, AI_tank[num].y);      //清除该坦克
		}
		bullet->exist = 0;//消除子弹
		score += 100;//得分
		GoToxy(102, 5);             //在副屏幕上打印出分数
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY
			| FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
		printf("%d ", score);
	}
	else if (map[y][x] == 200 && bullet->my == 0)   //若敌方子弹击中我的坦克
	{
		my_tank.alive = 0;//存活为1，死亡为0
		ClearTank(my_tank.x, my_tank.y);//清除MY坦克图像
		bullet->exist = 0;//子弹存在与否的变量，1为存在，0为没有
		my_tank.revive++;      //我的坦克复活次数+1(∵我的坦克复活次数与生命值有关∴放在这里自减)
		score -= 100;            //分数减少
		GoToxy(102, 5);         //在副屏幕上打印出分数
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY
			| FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
		printf("%d   ", score);
		GoToxy(102, 7);         //在副屏幕打印出我的剩余生命值
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY
			| FOREGROUND_GREEN);
		printf("%d   ", MAX_LIFT - my_tank.revive);
	}
	else if (map[y][x] == 9)      //子弹碰到家(无论是谁的子弹)
	{
		bullet->exist = 0;
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_BLUE
			| FOREGROUND_RED | FOREGROUND_GREEN);
		GoToxy(38, 37);	 printf("      ");
		GoToxy(38, 38);	 printf("◢◣  ");
		GoToxy(38, 39);	 printf("███");
		GameOver(1);           //游戏结束,传入1代表老家被毁
	}
}
void PrintBullet(int x, int y, int T)               //打印子弹（人机共用）
{
	if (T == 1)          //  T==1 表示子弹当前坐标在陆地上
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED
			| FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
	else if (T == 2)     //  T==2 表示子弹当前坐标在水面上
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED
			| FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY | BACKGROUND_BLUE);
	GoToxy(2 * x, y);
	printf("o");
}
void ClearBullet(int x, int y, int T)             //清除子弹（人机共用）
{
	GoToxy(2 * x, y);
	if (T == 2)        //  T==2 表示子弹当前坐标在水面上
	{
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY
			| BACKGROUND_BLUE | FOREGROUND_BLUE | FOREGROUND_GREEN);
		printf("～");
	}
	else if (T == 1)   //  T==1 表示子弹当前坐标在陆地上
	{
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_BLUE);
		printf("  ");
	}
}
int BulletCheak(int x, int y)                       //判断子弹前面的情况（人机共用）
{
	//判断子弹当前位置情况,判断子弹是否碰撞,是否位于水面上。
	//有障碍返回0,无障碍且子弹在地面返回1，子弹在水面上返回2
	if (map[y][x] == 0)
		return 1;
	else if (map[y][x] == 5)
		return 2;
	else
		return 0;
}